package com.huaxin.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaxin.device.dto.ResponseCode;
import com.huaxin.device.dto.ResponseResult;
import com.huaxin.device.dto.request.SwitchCabinetTypeCreateReqDTO;
import com.huaxin.device.dto.request.SwitchCabinetTypePageListReqDTO;
import com.huaxin.device.dto.request.SwitchCabinetTypeUpdateReqDTO;
import com.huaxin.device.feignClients.InspectionFeignService;
import com.huaxin.device.mapper.SwitchCabinetMapper;
import com.huaxin.device.mapper.SwitchCabinetTypeMapper;
import com.huaxin.device.mapping.SwitchCabinetTypeMapping;
import com.huaxin.device.models.SwitchCabinetType;
import com.huaxin.device.service.SwitchCabinetTypeService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.webjars.NotFoundException;

import static org.springframework.util.StringUtils.hasText;

@Service
@RequiredArgsConstructor
public class SwitchCabinetTypeServiceImpl extends ServiceImpl<SwitchCabinetTypeMapper, SwitchCabinetType> implements SwitchCabinetTypeService {

    private final ApplicationContext applicationContext;
    private final SwitchCabinetTypeMapping mapping;
    private final SwitchCabinetMapper switchCabinetMapper;
    private final InspectionFeignService inspectionFeignService;

    @Override
    public ResponseResult<SwitchCabinetType> create(SwitchCabinetTypeCreateReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        // 检查 cabinetCode + orgId 是否已存在
        if (existsByFields(SwitchCabinetType::getCode, in.getCode(), in.getOrgId(), null)) {
            return ResponseResult.failure(ResponseCode.BAD_REQUEST, "编号已存在", null);
        }

        SwitchCabinetType entity = mapping.toEntity(in);
        if (!save(entity)) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "添加失败，请稍后再试！", null);
        }
        SwitchCabinetType created = getById(entity.getId());
        return ResponseResult.ok(created);
    }

    @Override
    public SwitchCabinetType getByTypeId(String id) {
        if (id == null || id.trim().isEmpty()) {
            throw new IllegalArgumentException("ID不能为空");
        }
        SwitchCabinetType entity = getById(id);
        if (entity == null) {
            throw new NotFoundException("变电箱不存在");
        }
        return entity;
    }

    @Override
    public ResponseResult<String> update(SwitchCabinetTypeUpdateReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        SwitchCabinetType entity = getByTypeId(in.getId());

        mapping.updateEntity(in, entity);
        if (!updateById(entity)) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "更新失败，请稍后再试！", null);
        }
        return ResponseResult.ok("更新成功");
    }

    @Override
    public ResponseResult<String> delete(String id) {
        SwitchCabinetType entity = getByTypeId(id);

        // 检查该类型是否被使用
        if (switchCabinetMapper.existsByType(entity.getCode())) {
            return ResponseResult.failure(ResponseCode.BAD_REQUEST, "该类型已被配电箱使用，请先解除关联关系", null);
        }
        if (inspectionFeignService.existsByCabinetType(entity.getCode())) {
            return ResponseResult.failure(ResponseCode.BAD_REQUEST, "该类型已被巡检模板使用，请先解除关联关系", null);
        }

        boolean removed = this.applicationContext.getBean(SwitchCabinetTypeService.class).removeById(id);
        if (!removed) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "删除失败，请稍后重试", null);
        }
        return ResponseResult.ok("删除成功！");
    }

    @Override
    public ResponseResult<IPage<SwitchCabinetType>> pageQuery(SwitchCabinetTypePageListReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        IPage<SwitchCabinetType> page = new Page<>(in.getPageNum(), in.getPageSize());
        LambdaQueryWrapper<SwitchCabinetType> wrapper = new LambdaQueryWrapper<>();

        // 关键字搜索：名称、编号、位置
        if (hasText(in.getKeyword())) {
            wrapper.and(w -> w.like(SwitchCabinetType::getName, in.getKeyword())
                    .or().like(SwitchCabinetType::getCode, in.getKeyword())
                    .or().like(SwitchCabinetType::getDescription, in.getKeyword()));
        }

        // 所属组织
        if (hasText(in.getOrgId())) {
            wrapper.eq(SwitchCabinetType::getOrgId, in.getOrgId());
        }

        // 按创建时间倒序
        wrapper.orderByDesc(SwitchCabinetType::getCreatedAt);

        IPage<SwitchCabinetType> resultPage = page(page, wrapper);
        return ResponseResult.ok(resultPage);
    }

    /**
     * 检查多个字段值组合是否已存在（排除当前ID）
     *
     * @param fieldGetter 字段Getter
     * @param fieldValue  字段值
     * @param orgId       组织ID
     * @param excludeId   要排除的ID（可为null）
     * @return 是否存在匹配记录
     */
    private boolean existsByFields(
            SFunction<SwitchCabinetType, ?> fieldGetter,
            Object fieldValue,
            String orgId,
            String excludeId) {

        if (fieldGetter == null) return false;

        LambdaQueryWrapper<SwitchCabinetType> wrapper = new LambdaQueryWrapper<>();

        if (fieldValue == null ||
                (fieldValue instanceof CharSequence cs && cs.toString().trim().isEmpty())) {
            wrapper.and(wrapper1 -> wrapper1
                    .isNull(fieldGetter)
                    .or().eq(fieldGetter, "")
            );
        } else {
            wrapper.eq(fieldGetter, fieldValue.toString().trim());
        }

        if (orgId == null || orgId.trim().isEmpty()) {
            wrapper.and(wrapper1 -> wrapper1
                    .isNull(SwitchCabinetType::getOrgId)
                    .or().eq(SwitchCabinetType::getOrgId, "")
            );
        } else {
            wrapper.eq(SwitchCabinetType::getOrgId, orgId.trim());
        }

        if (excludeId != null && !excludeId.trim().isEmpty()) {
            wrapper.ne(SwitchCabinetType::getId, excludeId.trim());
        }

        return this.count(wrapper) > 0;
    }
}